﻿namespace Sai.Core.Introspection
{
	using System;
	using System.Xml.Serialization;

	public class TypeName : IComparable<TypeName>, ISourceCodeProvider
	{
        private FullyQualifiedName _name;

		public TypeName()
		{
		}

        public TypeName(Namespace namespaceName, Name typeName)
        {
            this.FullName = namespaceName + typeName;
        }

		public TypeName(FullyQualifiedName fullyQualifiedName)
		{
            this.FullName = fullyQualifiedName;
		}

		[XmlAttribute("Name")]
		public string Name 
        { 
            get
            {
                return this._name.Name.ToString();
            }
            set
            {
                this._name.Name = new Name(value);
            }
        }

        [XmlIgnore]
        public string SafeName
        {
            get
            {
                return this._name.Name.Value.HtmlSafeTypeName();
            }
        }

		[XmlAttribute("Namespace")]
		public string Namespace 
        { 
            get
            {
                return this._name.Namespace.Name;
            }
            set
            {
                this._name.Namespace = new Namespace(value);
            }
        }

        [XmlIgnore]
		public FullyQualifiedName FullName
		{
			get
            {
                return this._name;
            }
            set
            {
                this._name = value;
            }
		}

        [XmlAttribute("FullName")]
        public string SafeFullName
        {
            get
            {
                return this.FullName.ToString().HtmlSafeTypeName();
            }
            set
            {
                this.FullName = new FullyQualifiedName(value);
            }
        }

		public bool InGlobalNamespace
		{
			get
			{
				return this._name.Namespace == Sai.Core.Introspection.Namespace.GlobalNamespace;
			}
		}

		public bool InSystemNamespace
		{
			get
			{
                return this._name.Namespace == Sai.Core.Introspection.Namespace.SystemNamespace;
			}
		}

		public static bool operator ==(TypeName a, TypeName b)
		{
			if (object.ReferenceEquals(a, b))
			{
				return true;
			}

			if (((object)a == null) || ((object)b == null))
			{
				return false;
			}

            return a._name == b._name;
		}

		public static bool operator !=(TypeName a, TypeName b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}

			TypeName anotherType = obj as TypeName;

			if ((object)anotherType == null)
			{
				return false;
			}

            return this._name == anotherType._name;
		}

		public bool InSameNamespaceAs(TypeName other)
		{
			return this._name.Namespace.CompareTo(other._name.Namespace) == 0;
		}

		public override string ToString()
		{
			return this._name.ToString();
		}

		public override int GetHashCode()
		{
			return this.FullName.GetHashCode();
		}

		public int CompareTo(TypeName other)
		{
			if (other == null)
			{
				return 1;
			}

			return this._name.CompareTo(other._name);
		}

        public SourceCode ToCode()
		{
            SourceCode code = new SourceCode();

            if (this._name.Namespace == Sai.Core.Introspection.Namespace.SystemNamespace)
            {
                FullyQualifiedName replaced = FullyQualifiedName.ConvertTypeAlias(this._name);
                code.Add(new TypeNameTag(replaced.Name.Value));
            }
            else
            {
                code.Add(new TypeNameTag(this.Name));
            }

            return code;
		}
	}
}
